EEPROMデータロガ
1. PIC16F877Aデータロガ(内蔵EEPROM):
電池や太陽電池などの計時測定に用いるために、電源を切ってもデータが残り、屋外などのパソコンの届かないところでも使用することができれば便利である。
ここでは、PICマイコンに内蔵されている、消去可能な不揮発性メモリ:
EEPROM(PIC16F877Aでは 256バイト)を活用して、電圧・電流のデータを LCDでモニターしながら 頃合を見て記録し、後で 記録内容を USBに出力する装置を作製した。
AD変換にかけるための ch0:入力電圧は、アッテネーターを付けて調整できるようにし、ch1:入力電流は、1Ωの抵抗にかかる電圧をオペアンプで増幅して電圧入力を換算した。 参照電圧 VREF+は ツェナーシャントレギュレーターTL431により 3.072Vに固定した。 この条件で、LCD、シリアル共、10進表示関数の中に、電圧の倍率: v=v*33、電流の倍率: v=v*5 を設定した。
したがって、測定範囲は、電圧: 〜 3.375V、 (電流はこの場合 〜400mA以上)
であり、分解能は、電圧で 3〜4mV、電流で 0.5mA程度となる。 ただし
電流では、10mA以下ではより低めに測定される。作製した回路では 電流測定用の抵抗に
1Ωを用いたが、さらに 0.1Ωの抵抗を用いるためには もう1段精度の高いオペアンプ(INA128など)で増幅する必要がある。
測定実験では、印加電圧 0〜4V、 負荷抵抗 51Ω10W、10Ω10Wで行なった。
LCDへの表示は、記録しているデータ数、および、現在の 電圧(V)、電流(mA)で、データ数が20になると記録は停止する。
( 注) LCDの RS、E、R/Wを RD1、2、3で駆動しようとしたが、LCDは動かなかった(?)ので、RB1、2、3
に変更した)
記録のゲートタイムは、メイン関数で タイマ0 の繰り返しで行なった。(* タイマ1などの 頻繁な割り込みを掛けると
シリアル出力が止まってしまうので使えなかった。外部からの 1秒程度の遅い基準信号で
短時間割込むならば問題ないと思われる)
PIC16Fシリーズは USBを持たないので、USB−シリアル変換をプログラム済みのPIC18F14K50 を用意し、877Aのシリアル端子 RX、TX をたすきがけにつなげる。14K50への電源はUSBにつなげたときにのみUSBから供給されるので、本体の5V電源をつながない事。(
→ PIC18USB通信 3(2) )
2個のトグルスイッチは、それぞれ、EEPROMへの記録/停止、測定ゲートタイムの切替(5秒/1分)、 また 2個のタクトスイッチは、それぞれ、USB出力、記録データの消去 に使用した。 PIC16シリーズは INT入力が1つしかないので、RB4〜7の変化による割込み(チェンジオンインタラプト)も使用した。そのため 液晶表示用データピンはRD4〜7を用いた。また、タクトスイッチ入力(コンデンサー無し)による短い割込みならば、問題なくシリアル通信と両立した。
また、EEPROMの消去は 0を使用アドレス分書き込むことによって行なった。
EEPROMに記録するのは AD変換後の 電圧、電流それぞれの ADRESH、ADRESLの値で、データの個数1バイトと、各データ 4バイト×データ個数分 を記録する。 PIC16シリーズの場合、EEPROMへの書き込み、読み出しの文法は簡単で(HI−TEC
Cに EEPROMのマクロがすでに入っている)、 eeprom_write(アドレス、1バイトのデータ)、 eeprom_read(アドレス) でそのまま行なう。 ここでは、記録数を 20セットとしたが、内蔵 EEPROMが256バイトあるので、最大 63セットまで可能。
このプログラムでは、main関数の while(1)ループで LCD表示と
すべてのスイッチ操作が行なわれるので、データをUSBに送るときは、ゲートタイム切替スイッチを5秒に戻してから行なうと 5秒以内に出力される。(さもないと 1分かかる。 1サイクル=30分に設定すれば30分もかかることになる!) 消去のときも同様。また、LCD表示も動きが固着される。
そこで、外部に 充分遅い 基準信号発生器(16F628A・10MHz水晶発振など)を付け、T1CKI
(×1/65536)に入れ、(頻度の低い)タイマ1割込みで記録時間を切り替えるようにすれば、測定時間切替レンジ数も増え、シリアル通信も妨害を受けず、この問題は解決する。
太陽電池(2V・250mAmax)で測定(負荷抵抗51Ω)した結果は、室内・窓際(3月)で
晴天で2.2V44mA、曇り空で0.5V10mA程度だった。
● ソース:
● PIC18 シリーズ で作る場合は、EECON1、2 を用いて、PIC内蔵EEPROMの
書き込み、読み出しの BYTE関数 を作って行なう。(↓)
2. PIC18F2550データロガ(外部EEPROM):
外付けの EEPROMを読み書きするには、I2C(I スクェア C)通信を用いる。 そのために、ヘッダ <i2c.h> を取り込み、通信のための関数群を設定する必要がある。
今回 PIC18F2550で作製したデータロガは、SSPCONを用いた 1バイト単位の書き込み関数、読み出し関数
で行なった。( ↓ 書込み、読み出しマクロ )
・ 1バイトの書き込み関数: unsigned char EByteWrite(unsigned char control, unsigned int address,unsigned char data) ・・・ ex) V = EByteWrite(0xA0,memadrs,'A');
・ 1バイトの読み出し関数: unsigned int EByteRead(unsigned char control, unsigned int address) ・・・ ex) data = EByteRead(0xA0,memadrs);
・ ページ書き込み関数: unsigned char EPageWrite(unsigned char
control,unsigned int address,unsigned char *wtptr)
・ シ−ケンシャル読み出し関数: unsigned char ESequentialRead(unsigned
char control,unsigned int address,unsigned char *rdptr,unsigned char length)
外部 EEPROMには 24LC256(シリアルI2C、256kbit(32kバイト×8ビット、最終アドレス0x7FFF = 32767バイト目)、400kHz(FastMode
400kbit/s)、プルアップ抵抗3.3kΩ)を用いた。 メモリ容量が充分なので、EEPROMはただ1個用いたが、8個まで拡張可能。
複数用いた場合の EEPROMどおしの識別には チップアドレス区別用のピンを用い、
A0、A1、A2をすべてアースに落として 000 (wp(ライトプロテクト)も0で解除)、すなわち
チップアドレスが 0 ならば、0b10100000 = 0xA0 となる。(A0 をプルアップして、アドレスを 001 としたチップならば、0b10100010 = 0xA2)
USBで直接 入出力できるように、また、USB Device - CDC - Basic Demo (これだけで20kバイトもある → PIC18USB温度計 )を改造しても充分メモリの容量があるように、PIC18F2550(フラッシュ32kバイト、RAM2048バイト)を用いた。
下記プログラムのビルド結果は、メモ帳の .hexファイルで 約32kバイトであり、2550で問題なく動作した。
計測の時間間隔を与えるクロック信号(1秒、10秒、1分 の切替)には、PIC16F628A・水晶発振による信号発生器を別途に作成(→ 調整可能な基準信号発生器 )して デジタルピンで受けるようにし、USBに極力影響を与えないように注意した。(INTやタイマー割込みは使わない) ただし、電源切替スイッチにより、一旦電源が切れてUSB電源に入れ直すので、書き込み時にUSBにトラブルがあっても確実にデータを送ることができる。
電源切替スイッチは、外部と USBの電源が重ならないように 切り離す役割も持っている。
また、2550は、14K50と ADコンバーターの書式が若干異なるので注意。
例によって、CDC-Basic-Demo (* MCHPFSUSB v2010_02_09 版の r2550eb から CDC-BASIC-DEMO
使用)は、INT2割込みの設定だけでUSBが止まってしまうので、PIC16F628Aからのゲート信号は幅の広いパルス(約510mSに固定
= while(1)ループの周期を1個だけ含む ループと同じ時間幅)とし、デジタル信号として RB2で受けたが、18F2550 のループ側の時間設定により、1000回に1回程度の数え落しとなる。
これによって、USB電源だけを用いても問題なく動作した。 メモリ・クリア用のタクトスイッチ入力も RE3で受け、割込みは全く使わなかった。RE3で受けるために コンフィグレーションのMCLRE はOFFにする。(ONではPICの電源がリセットされる)
ADコンバーターの書式は、14K50と異なり、ADCON0、1、2 を設定し、adc.hのヘッダを取り込み、SetChanADC(
) で行なった。
EEPROMへのバイト読出し、書込みは、i2c.hを取り込み、上記の関数を使用した。 書込みには時間がかかるので、約12mSを挿入した。(もっと短くても良い) 読出しは、12MHzの動作クロック(20MHzレゾネータ発振)で問題なく行なえた。
AD変換結果のデータは、1.と同様に、電圧、電流のそれぞれの ADRESH、ADRESLの数値を分けて、データ1セットにつき4つの記録バイトを用いて順次記録・読出しした。
また、PreocessIO におけるUSBへの送信は、if(mUSBUSRTTIsTxTrfReady( ){ から CDCTxService( ) までのループを、1つの j に対し2回繰り返すことによって、奇数番目のみしか出力しないという”歯抜け”を防ぐようにした。(このUSB処理は、1回送信すると
次の回は送信を受け付けないようになっているらしい)
ゲートタイムは、1分、10秒、および、テスト用に短時間(約0.7秒)の3種類切り替えるようにした。PIC16F628Aの発振用水晶
10MHzより、動作クロック2.5MHz。(例えば、太陽電池を昼間の6時間、1分毎にデータ採取すれば、360セットのデータ数になる。この場合の時間誤差は
割込みループの回数のみの設定で 18秒以内。これ以上の時間精度が必要ならば、TMR1H、Lを調整する。)
デジタル入力なので、消去用のタクトスイッチの押し心地は悪く 2〜3回押さないと動作しない場合もあった。 EEPROMデータの消去には データの個数だけ0を書き込むので、1000セットのデータ消去に(書込みの待ち時間を短くしているので、)約5秒かかる。
パソコンへの出力は、USBに接続してから、TeraTerm等のシリアル通信ソフトを開き、パソコンの
Enterキー(0x0A)を押すことによって、データNO、電圧(V)、電流(mA)、および、各電圧×電流を順次総和した積算値(long変数)
を1行ずつ表示する。(1000行表示するのに約13秒かかる) 通信速度は任意。
この積算値のうち一番下の数値は、測定時のゲートタイムを掛けることによって
電力積算値(mW・hr など)となる。
外部EEPROMは かなり多くのデータを記録することができる(24LC256 1個で 最大32kバイト
= 4個1セットのデータで 8000セット)ので、パソコンに出力されたデータは、パソコンのソフトによって処理する方が良いと思われる。 因みに、Microchip社のI2C EEPROM としては 24LC64(64kbit・8kバイト)、24LC1025(1Mbit)などがある。
● ソース: ソース(628A):